home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianTQ2026F.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  11KB  |  448 lines

  1. /*
  2.  * ScianTQ2026F.c
  3.  *   Written by Marvin Landis
  4.  *   April 10, 1992
  5.  *   Controls the Panasonic TQ-2026F optical disk recorder
  6. */
  7.  
  8. #include "Scian.h"
  9. #include "ScianTypes.h"
  10. #include "ScianWindows.h"
  11. #include "ScianDialogs.h"
  12. #include "ScianIDs.h"
  13. #include "ScianErrors.h"
  14. #include "ScianTQ2026F.h"
  15. #include "ScianRecorders.h"
  16.  
  17. #ifdef TERMIO
  18.  
  19. /* Internal prototypes */
  20. #ifdef PROTO
  21. void TQ_ReportError(int, char *);
  22. void TQ_SendCmd(int, char *);
  23. static int TQ_OpenPort(char *, int);
  24. static int TQ_VerifyResponse(int, char *, int);
  25. static ObjPtr ConnectTQ2026F(ObjPtr);
  26. static ObjPtr PrepareToRecordTQ2026F(ObjPtr, long);
  27. static ObjPtr StopRecordingTQ2026F(ObjPtr);
  28. static ObjPtr DisconnectTQ2026F(ObjPtr);
  29. static ObjPtr SnapOneFrameTQ2026F(ObjPtr);
  30. #endif
  31.  
  32. void TQ_ReportError(error, procName)
  33. /* Reports the error returned from the TQ_VerifyResponse function */
  34. int error;
  35. char *procName;
  36. {
  37.     switch (error) {
  38.     case -100:
  39.            ReportError(procName, "STX not received");
  40.            break;
  41.     case -101:
  42.            ReportError(procName, "Completion response is invalid");
  43.            break;
  44.     case -102:
  45.            ReportError(procName, "Timeout error");
  46.            break;
  47.     default:
  48.            ReportError(procName, "NAK received from recorder");
  49.            break;
  50.     }
  51. }
  52.  
  53. #ifdef PROTO
  54. static int TQ_OpenPort(char *devName, int baudRate)
  55. #else
  56. static int TQ_OpenPort(devName, baudRate)
  57. char *devName;
  58. int baudRate;
  59. #endif
  60. /* Opens a port to the recorder, returns it if successful */
  61. {
  62.     int portDev;
  63.     struct termio ioStuff;
  64.  
  65.     portDev = open(devName, O_RDWR | O_NDELAY | O_EXCL);
  66.     if (portDev < 0)
  67.     {
  68.     return portDev;
  69.     }
  70.     ioctl(portDev, TCGETA, &ioStuff);
  71.     ioStuff . c_oflag = 0;
  72.     ioStuff . c_iflag = IGNBRK;
  73.     ioStuff . c_lflag &= ~( ICANON | ECHO );
  74.  
  75.     /*Make cflag from baud rate*/
  76.     switch(baudRate)
  77.     {
  78.     case RB_300:
  79.         ioStuff . c_cflag = (unsigned short) (B300 | CS8 | CLOCAL | CREAD | CSTOPB);
  80.         break;
  81.     case RB_1200:
  82.         ioStuff . c_cflag = (unsigned short) (B1200 | CS8 | CLOCAL | CREAD);
  83.         break;
  84.     case RB_2400:
  85.         ioStuff . c_cflag = (unsigned short) (B2400 | CS8 | CLOCAL | CREAD);
  86.         break;
  87.     case RB_4800:
  88.         ioStuff . c_cflag = (unsigned short) (B4800 | CS8 | CLOCAL | CREAD);
  89.         break;
  90.     case RB_9600:
  91.         ioStuff . c_cflag = (unsigned short) (B9600 | CS8 | CLOCAL | CREAD);
  92.         break;
  93.     case RB_19200:
  94.         ioStuff . c_cflag = (unsigned short) (B19200 | CS8 | CLOCAL | CREAD);
  95.         break;
  96.     }
  97.  
  98.     ioStuff . c_cc[4] = 1;
  99.     ioStuff . c_cc[0] = 1;
  100.  
  101.     ioctl(portDev, TCSETA, &ioStuff);
  102.     return portDev;
  103. }
  104.  
  105. void TQ_SendCmd(portDev, command)
  106. /* Encapsulates the command in a STX / ETX pair, then sends the command
  107.  * to the recorder.
  108. */
  109. int portDev;
  110. char *command;
  111. {
  112.     char fullcommand[256];
  113.     int bytesWritten;
  114.  
  115.     sprintf(fullcommand, "%c%s%c", STX, command, ETX);
  116.     bytesWritten = write(portDev, fullcommand, strlen(fullcommand));
  117. }
  118.  
  119. static int TQ_VerifyResponse(portDev, command, timeout)
  120. /* Reads the completion response from the recorder, checks to see if it is
  121.  * the correct response, and returns the result. Returns either a 0 or a
  122.  * positive integer (the number of remaining frames to be recorded, as returned
  123.  * from the RECORD_REMAIN command) iff the command is successfully completed.
  124.  * Returns the following negative numbers if there was a problem decoding the
  125.  * command:
  126.  *
  127.  * -1 to -99            NAK response error
  128.  * -100                 STX not received
  129.  * -101                 Completion response does not match the command
  130.  * -102                 Timeout
  131. */
  132. int portDev;
  133. char *command;
  134. int timeout;
  135. {
  136.     char retVal[256], fullRetVal[256];
  137.     int i, j;
  138.     int bytesRead;
  139.     int retInt = 0;
  140.     long startTime, curTime;
  141.     struct tms buffer;
  142.  
  143.     startTime = times(&buffer);
  144.     strcpy(fullRetVal, "");
  145.     do
  146.     {
  147.     sleep(1);     /* Couldn't get consistent results without this delay */
  148.     bytesRead = read(portDev, retVal, 256);
  149.     if (bytesRead > 0)
  150.     {
  151.         retVal[bytesRead] = 0;
  152.         strcat(fullRetVal, retVal);
  153.         if (fullRetVal[0] != ACK)
  154.         {
  155.         /* NAK has been received.  Decode the error number, and return
  156.          * the negative value of the error
  157.         */
  158.         j = 0;
  159.         while (fullRetVal[++j])
  160.             retInt = retInt * 10 + (fullRetVal[j] - '0');
  161.         return -retInt;
  162.         }
  163.         else
  164.         {
  165.         /* ACK has been received.  STX is next, then the completion
  166.          * response.  Optional number follows, then terminates with
  167.          * an ETX.
  168.         */
  169.         j = 0;
  170.         while (fullRetVal[++j])
  171.         {
  172.  
  173.             /* The very first time an ON8: command is sent to the
  174.              * recorder, the ACK is followed by a CR/LF.  After ON8:
  175.              * is executed, there are no more CR/LF's sent.  This
  176.              * statement takes care of that first CR/LF.
  177.             */
  178.             if (fullRetVal[j] == CR) j += 2;
  179.  
  180.             if (fullRetVal[j] != STX) return -100;
  181.             if (fullRetVal[++j] == 'E') {
  182.             retInt = 0;
  183.             while (fullRetVal[++j] != ETX)
  184.                 retInt = retInt * 10 + (fullRetVal[j] - '0');
  185.             retInt = -retInt;
  186.             }
  187.             else
  188.             {
  189.             if (fullRetVal[j] != command[0]) return -101;
  190.             if (fullRetVal[++j] != command[1]) return -101;
  191.             retInt = 0;
  192.             while (fullRetVal[++j] != ETX)
  193.                 retInt = retInt * 10 + (fullRetVal[j] - '0');
  194.             return retInt;
  195.             }
  196.         }
  197.         }
  198.     }
  199.     curTime = times(&buffer);
  200.     } while (curTime < startTime + timeout * HEARTBEAT);
  201.     return -102;
  202. }
  203.  
  204. static ObjPtr ConnectTQ2026F(object)
  205. /* Connects to the Panasonic TQ-2026F.  Returns true iff successful */
  206. ObjPtr object;
  207. {
  208.     int portDev;
  209.     int response;
  210.     char *devName;
  211.     int baudRate;
  212.     ObjPtr var;
  213.  
  214.     MakeVar(object, PORTDEV);
  215.     var = GetStringVar("ConnectTQ2026F", object, PORTDEV);
  216.     if (var)
  217.     {
  218.     devName = GetString(var);
  219.     }
  220.     else
  221.     {
  222.     devName = TQ2026F_DEV;
  223.     }
  224.  
  225.     MakeVar(object, BAUDRATE);
  226.     var = GetIntVar("ConnectTQ2026F", object, BAUDRATE);
  227.     if (var)
  228.     {
  229.     baudRate = GetInt(var);
  230.     }
  231.     else
  232.     {
  233.     baudRate = RB_9600;
  234.     }
  235.  
  236.     /*Open the serial port*/
  237.     portDev = TQ_OpenPort(devName, baudRate);
  238.     if (portDev < 0)
  239.     {
  240.     return ObjFalse;
  241.     }
  242.  
  243.     /*Now that a port is open, connect to it*/
  244.     TQ_SendCmd(portDev, ONLINE);
  245.     response = TQ_VerifyResponse(portDev, ONLINE, 5);
  246.     if (response == 0)
  247.     {
  248.  
  249.     /* Exercise the recorder a little to verify it is ready */
  250.     TQ_SendCmd(portDev, STEP_FORWARD);
  251.     response = TQ_VerifyResponse(portDev, STEP_FORWARD, 20);
  252.     if (response == 0)
  253.     {
  254.         TQ_SendCmd(portDev, STEP_BACKWARD);
  255.         response = TQ_VerifyResponse(portDev, STEP_BACKWARD, 5);
  256.         if (response == 0) {
  257.         SetVar(object, PORTNUMBER, NewInt(portDev));
  258.         return ObjTrue;
  259.         }
  260.     }
  261.  
  262.     }
  263.     close(portDev);
  264.     TQ_ReportError(response, "ConnectTQ2026F");
  265.     return ObjFalse;
  266. }
  267.  
  268. static ObjPtr PrepareToRecordTQ2026F(object, nFrames)
  269. /* Prepares to record nFrames on an TQ2026F.  Returns true iff successful. */
  270. ObjPtr object;
  271. long nFrames;
  272. {
  273.     ObjPtr port;
  274.     int portDev;
  275.     int remFrames;
  276.     int response;
  277.     char searchCommand[256];
  278.  
  279.     port = GetVar(object, PORTNUMBER);
  280.     if (port)
  281.     {
  282.     portDev = GetInt(port);
  283.  
  284.     do
  285.     {
  286.  
  287.         /* Manual record mode searches for next blank recording area. */
  288.         TQ_SendCmd(portDev, MANUAL_RECORD_MODE);
  289.         response = TQ_VerifyResponse(portDev, MANUAL_RECORD_MODE, 400);
  290.         if (response < 0)
  291.         {
  292.         TQ_ReportError(response, "PrepareToRecordTQ2026F");
  293.         return ObjFalse;
  294.         }
  295.  
  296.         /* Now find out how many blank frames there are to record on */
  297.         TQ_SendCmd(portDev, RECORD_REMAIN);
  298.         remFrames = TQ_VerifyResponse(portDev, RECORD_REMAIN, 5);
  299.         if (remFrames < 0) {
  300.         TQ_ReportError(response, "PrepareToRecordTQ2026F");
  301.         return ObjFalse;
  302.         }
  303.  
  304.         /* If not enough, prepare to search for more */
  305.         if (remFrames < nFrames)
  306.         {
  307.         TQ_SendCmd(portDev, RECORD_MODE_CLEAR);
  308.         response = TQ_VerifyResponse(portDev, RECORD_MODE_CLEAR, 5);
  309.         if (response < 0)
  310.         {
  311.             TQ_ReportError(response, "PrepareToRecordTQ2026F");
  312.             return ObjFalse;
  313.         }
  314.  
  315.         /* Search to the next recorded frame, then try again */
  316.         sprintf(searchCommand, "%s+%d:", SEARCH, remFrames);
  317.         TQ_SendCmd(portDev, searchCommand);
  318.         response = TQ_VerifyResponse(portDev, SEARCH, 5);
  319.         if (response < 0)
  320.         {
  321.             TQ_ReportError(response, "PrepareToRecordTQ2026F");
  322.             return ObjFalse;
  323.         }
  324.         }
  325.     } while (remFrames < nFrames);
  326.     return ObjTrue;
  327.     }
  328.     return ObjFalse;
  329. }
  330.  
  331. static ObjPtr StopRecordingTQ2026F(object)
  332. /* Stops recording */
  333. ObjPtr object;
  334. {
  335.     ObjPtr port;
  336.     int response;
  337.  
  338.     port = GetVar(object, PORTNUMBER);
  339.     if (port)
  340.     {
  341.     int portDev;
  342.     portDev = GetInt(port);
  343.  
  344.     TQ_SendCmd(portDev, RECORD_MODE_CLEAR);
  345.     response = TQ_VerifyResponse(portDev, RECORD_MODE_CLEAR, 5);
  346.     if (response == 0)
  347.         return ObjTrue;
  348.     else
  349.     {
  350.         TQ_ReportError(response, "StopRecordingTQ2026F");
  351.         return ObjFalse;
  352.     }
  353.     }
  354.     return ObjFalse;
  355. }
  356.  
  357. static ObjPtr DisconnectTQ2026F(object)
  358. /* Takes the recorder offline */
  359. ObjPtr object;
  360. {
  361.     int portDev;
  362.     ObjPtr port;
  363.     int response;
  364.  
  365.     port = GetVar(object, PORTNUMBER);
  366.     if (port)
  367.     {
  368.     portDev = GetInt(port);
  369.     TQ_SendCmd(portDev, OFFLINE);
  370.     response = TQ_VerifyResponse(portDev, OFFLINE, 5);
  371.     if (response == 0)
  372.     {
  373.         close(portDev);
  374.         SetVar(object, PORTNUMBER, NULLOBJ);
  375.         return ObjTrue;
  376.     }
  377.     else
  378.     {
  379.         TQ_ReportError(response, "DisconnectTQ2026F");
  380.         return ObjFalse;
  381.     }
  382.     }
  383.     return ObjFalse;
  384. }
  385.  
  386. static ObjPtr SnapOneFrameTQ2026F(object)
  387. /* Records one frame on the Panasonic recorder */
  388. ObjPtr object;
  389. {
  390.     int portDev;
  391.     int response;
  392.     ObjPtr port;
  393.  
  394.     port = GetVar(object, PORTNUMBER);
  395.     if (port)
  396.     {
  397.     portDev = GetInt(port);
  398.     TQ_SendCmd(portDev, RECORD_FRAME);
  399.     response = TQ_VerifyResponse(portDev, RECORD_FRAME, 5);
  400.     if (response ==  0)
  401.         return ObjTrue;
  402.     else
  403.     {
  404.         TQ_ReportError(response, "SnapOneFrameTQ2026F");
  405.         return ObjFalse;
  406.     }
  407.     }
  408.     return ObjFalse;
  409. }
  410. #endif
  411.  
  412. #ifdef PROTO
  413. void InitTQ2026F(void)
  414. #else
  415. void InitTQ2026F()
  416. #endif
  417. /* Return a new TQ-2026F object */
  418. {
  419. #ifdef TERMIO
  420.     ObjPtr recorder;
  421.     char *devName;
  422.  
  423.     recorder = NewRecorder(commRecorderClass, "TQ-2026F", "Panasonic");
  424.     SetMethod(recorder, CONNECT, ConnectTQ2026F);
  425.     SetMethod(recorder, DISCONNECT, DisconnectTQ2026F);
  426.     SetMethod(recorder, PREPARETORECORD, PrepareToRecordTQ2026F);
  427.     SetMethod(recorder, STOPRECORDING, StopRecordingTQ2026F);
  428.     SetMethod(recorder, SNAPONEFRAME, SnapOneFrameTQ2026F);
  429.  
  430.     devName = getenv("SCIAN_RECORDER_DEV");
  431.     if (!devName || !devName[0])
  432.     {
  433.     devName = TQ2026F_DEV;
  434.     }
  435.     SetVar(recorder, PORTDEV, NewString(devName));
  436.  
  437.     RegisterRecorder(recorder);
  438. #endif
  439. }
  440.  
  441. #ifdef PROTO
  442. void KillTQ2026F(void)
  443. #else
  444. void KillTQ2026F()
  445. #endif
  446. {
  447. }
  448.